﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using Kugar.Core;
using System.Linq;
using Expression = System.Windows.Expression;

namespace Kugar.Core.SL4.Control
{
    public class DataGridDoubleClickBehavior : Behavior<DataGrid>
    {
        private readonly MouseClickManager _gridClickManager;
        public event EventHandler<MouseButtonEventArgs> DoubleClick;
        public DataGridDoubleClickBehavior()
        {
            _gridClickManager = new MouseClickManager(AssociatedObject, 500);
            _gridClickManager.DoubleClick += _gridClickManager_DoubleClick;
        }
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.LoadingRow += OnLoadingRow;
            AssociatedObject.UnloadingRow += OnUnloadingRow;
        }
        void OnUnloadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp -= _gridClickManager.HandleClick;
        }
        void OnLoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp += _gridClickManager.HandleClick;
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.LoadingRow -= OnLoadingRow;
            AssociatedObject.UnloadingRow -= OnUnloadingRow;
        }
        void _gridClickManager_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (DoubleClick != null)
                DoubleClick(sender, e);
        }
    }

    /// <summary>
    ///     显示行号的列
    /// </summary>
    ///<example>
    ///     在Xaml中：
    ///    (DataGridRowIndexColumn Header="标题" /)
    /// </example>
    public class DataGridRowIndexColumn : DataGridColumn
    {
        /*
         *  实现思路是这样的：
         * 1.集成DataGridColumn类，，生成一个新的列
         * 2.处理所属的DataGrid的LoadingRow事件生成行号，但由于在GenerateElement函数中，无法直接获得所属的DataGrid，
         *    而且当GenerateElement被调用的时候，在函数中的cell参数里，还没有RowIndex，并且该值也不可读，所以，为了第一次
         *    能显示行号，所以需要在GenerateElement创建返回的TextBlock控件中，订阅TextBlock 的Loaded事件，这样，在Loaded
         *    事件中，就可以藉由获取当前TextBlock所在的DataGridRow和DataGrid对象，再获取到相应的行号，并且订阅DataGrid的
         *    LoadingRow事件。
         * 3.在实际过程中发现，在一些情况下，TextBlock的Loaded事件中读取到的所属DataGridRow的GetIndex返回值会是错误的，
         *    所以，需要在LoadingRow中做实际的处理
         * 4.在这种情况下，DataGridRow的GetIndex返回值会是错误的：当记录数太多，需要DataGrid显示滚动条的时候，当滚动条向下
         *    滚动后，再往上滚动，这时候，原来的TextBlock获取到的行号就会是错误的。。因此，，才需要在LoadingRow中做处理
         */

        //用于判断是否已经订阅所属DataGrid的LoadingRow事件
        private bool isInjected = false;

        public DataGridRowIndexColumn()
        {
            IsReadOnly = true;
        }

        protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
        {
            return BuildNewTextBlock();
        }

        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
        {
            return BuildNewTextBlock();
        }

        private TextBlock BuildNewTextBlock()
        {
            var tb = new TextBlock();

            tb.TextAlignment = TextAlignment.Center;
            tb.HorizontalAlignment = HorizontalAlignment.Stretch;
            tb.VerticalAlignment = VerticalAlignment.Stretch;

            //订阅创建的TextBlock的Load事件
            tb.Loaded += IndexTextBlock_Loaded;

            return tb;
        }

        void IndexTextBlock_Loaded(object sender, RoutedEventArgs e)
        {
            var tb = (TextBlock)sender;

            var row = tb.GetParentControl<DataGridRow>();

            tb.Text = (row.GetIndex() + 1).ToString();

            if (!isInjected)  //如果当前还未订阅DataGrid的LoadingRow事件的话，，则在这里订阅，，只订阅一次
            {
                var grid = tb.GetParentControl<DataGrid>();

                grid.LoadingRow += grid_LoadingRow;

                grid.Unloaded += grid_Unloaded;

                isInjected = true;
            }

            tb.Loaded -= IndexTextBlock_Loaded;

        }

        void grid_Unloaded(object sender, RoutedEventArgs e)
        {
            var grid = (DataGrid)sender;

            grid.LoadingRow -= grid_LoadingRow;
            grid.Unloaded -= grid_Unloaded;
        }

        void grid_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            var grid = (DataGrid)sender;

            foreach (var col in grid.Columns)
            {
                if (col is DataGridRowIndexColumn)
                {
                    var tb = (TextBlock)col.GetCellContent(e.Row);
                    tb.Text = (e.Row.GetIndex() + 1).ToString();

                }
            }
        }

        protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
        {
            return false;
        }
    }
}
